package com.ruibang.glass.quality.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruibang.glass.common.constants.Constants;
import com.ruibang.glass.common.constants.RedisKey;
import com.ruibang.glass.common.domain.camunda.BpmProcessInstanceCreate;
import com.ruibang.glass.common.domain.camunda.BpmProcessInstanceStatus;
import com.ruibang.glass.common.domain.file.FileBusiness;
import com.ruibang.glass.quality.entity.BusinessAttributeDict;
import com.ruibang.glass.quality.entity.EngineeringChangeOrder;
import com.ruibang.glass.quality.feign.CamundaApi;
import com.ruibang.glass.quality.feign.FileApi;
import com.ruibang.glass.quality.mapper.EngineeringChangeOrderMapper;
import com.ruibang.glass.quality.service.BusinessAttributeDictService;
import com.ruibang.glass.quality.service.EngineeringChangeOrderService;
import com.teaming.cloud.framework2.autoconfigure.redis.RedisSingleService;
import com.teaming.cloud.framework2.autoconfigure.redis.RedisSingleService;
import com.teaming.cloud.framework2.common.constant.CommonConstant;
import com.teaming.cloud.framework2.common.model.ResultBody;
import com.teaming.cloud.framework2.common.pojo.PageRequest;
import com.teaming.cloud.framework2.common.pojo.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 工程变更单信息 服务实现类
 * </p>
 *
 * @author wujie
 * @since 2024-01-23
 */
@Service
public class EngineeringChangeOrderServiceImpl extends ServiceImpl<EngineeringChangeOrderMapper, EngineeringChangeOrder> implements EngineeringChangeOrderService {


    @Autowired
    private CommonService commonService;

    @Autowired
    private BusinessAttributeDictService attributeDictService;

    @Autowired
    private FileApi fileApi;

    @Autowired
    private CamundaApi camundaApi;

//    @Autowired
//    private RedisSingleService redisService;

    @Autowired
    private RedisSingleService redisService;

    private static final String CONTENT_FILE = "contentFile";//变更内容及原因文件关联

    private static final String RESULT_FILE = "resultFile";//变更验证检测结果文件关联

    private static final String INVOLVE_DEPT = "involve_dept";//涉及部门字典

    private static final String INVOLVE_FILE = "involve_file";//涉及文件

    private static final String INIT_CODE = "001"; //初始代码值

    @Override
    public String getChangeCode(){
        String dateStr = LocalDate.now().format(DateTimeFormatter.ofPattern(CommonConstant.DATE_FORMAT_YEAR_MONTH_UN_SEPARATE_TWO));
        String oldChangeCode = baseMapper.getMaxChangeCode();
        String changeCode  = "";
        if(StringUtils.isNotBlank(oldChangeCode)){
            long id = Long.parseLong(oldChangeCode);
            id = id + 1;
            changeCode = dateStr.concat(String.valueOf(id).substring(4));
        }else{
            changeCode = dateStr.concat(INIT_CODE);
        }
        return changeCode;
    }

    /***
     * 保存工程变更单信息
     * @param changeOrder
     */
    @Override
    public void saveInfo(EngineeringChangeOrder changeOrder) {
        this.save(changeOrder);
        List<BusinessAttributeDict> attributeDicts = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(changeOrder.getInvolveFiles())){
            changeOrder.getInvolveFiles().forEach(file->{
                BusinessAttributeDict attributeDict = new BusinessAttributeDict();
                attributeDict.setDictCode(file);
                attributeDict.setBusinessId(changeOrder.getChangeOrderId());
                attributeDict.setBelongAttribute(INVOLVE_FILE);
                attributeDicts.add(attributeDict);
            });
        }

        if(CollectionUtils.isNotEmpty(changeOrder.getInvolveDeptIds())){
            changeOrder.getInvolveDeptIds().forEach(dept->{
                BusinessAttributeDict attributeDict = new BusinessAttributeDict();
                attributeDict.setDictCode(dept);
                attributeDict.setBusinessId(changeOrder.getChangeOrderId());
                attributeDict.setBelongAttribute(INVOLVE_DEPT);
                attributeDicts.add(attributeDict);
            });
        }

        //保存更改订单扩展信息
        if(CollectionUtils.isNotEmpty(attributeDicts)){
            attributeDictService.saveBatch(attributeDicts);
        }

        //保存文件信息
        if(CollectionUtils.isNotEmpty(changeOrder.getContentFiles())){
            FileBusiness fileBusiness = new FileBusiness();
            fileBusiness.setFileIds(changeOrder.getContentFiles());
            fileBusiness.setBusinessId(changeOrder.getChangeOrderId());
            fileBusiness.setAttribute(CONTENT_FILE);
            fileApi.updateBusinessById(fileBusiness);
        }

        if(CollectionUtils.isNotEmpty(changeOrder.getResultFiles())){
            FileBusiness fileBusiness = new FileBusiness();
            fileBusiness.setFileIds(changeOrder.getResultFiles());
            fileBusiness.setBusinessId(changeOrder.getChangeOrderId());
            fileBusiness.setAttribute(RESULT_FILE);
            fileApi.updateBusinessById(fileBusiness);
        }

        //发起流程
        BpmProcessInstanceCreate instanceCreate = new BpmProcessInstanceCreate();
        instanceCreate.setBusinessKey(changeOrder.getChangeOrderId());
        instanceCreate.setMenuId(changeOrder.getMenuId());
        if(StringUtils.isNotBlank(changeOrder.getApplyUser())){
            Map<String, Object> variables = new HashMap<>();
            variables.put(Constants.PROCESS_INSTANCE_STARTER_USER_ID,changeOrder.getApplyUser());
            variables.put(Constants.PROCESS_INSTANCE_BUSINESS_KEY,changeOrder.getChangeOrderId());
            variables.put(Constants.PROCESS_INSTANCE_MENU_ID,changeOrder.getMenuId());
            instanceCreate.setVariables(variables);
        }
        commonService.startProcess(instanceCreate);
    }

    @Override
    public void updateInfo(EngineeringChangeOrder changeOrder) {
        if(CollectionUtils.isNotEmpty(changeOrder.getResultFiles())){
            FileBusiness fileBusiness = new FileBusiness();
            fileBusiness.setFileIds(changeOrder.getResultFiles());
            fileBusiness.setBusinessId(changeOrder.getChangeOrderId());
            fileBusiness.setAttribute(RESULT_FILE);
            fileApi.updateBusinessById(fileBusiness);
        }

        if(CollectionUtils.isNotEmpty(changeOrder.getDeleteResultFiles())){
            fileApi.deleteByFileIds(changeOrder.getDeleteResultFiles());
        }

        attributeDictService.deleteByBusinessId(changeOrder.getChangeOrderId());

        List<BusinessAttributeDict> attributeDicts = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(changeOrder.getInvolveFiles())){
            changeOrder.getInvolveFiles().forEach(file->{
                BusinessAttributeDict attributeDict = new BusinessAttributeDict();
                attributeDict.setDictCode(file);
                attributeDict.setBusinessId(changeOrder.getChangeOrderId());
                attributeDict.setBelongAttribute(INVOLVE_FILE);
                attributeDicts.add(attributeDict);
            });
        }

        if(CollectionUtils.isNotEmpty(changeOrder.getInvolveDeptIds())){
            changeOrder.getInvolveDeptIds().forEach(dept->{
                BusinessAttributeDict attributeDict = new BusinessAttributeDict();
                attributeDict.setDictCode(dept);
                attributeDict.setBusinessId(changeOrder.getChangeOrderId());
                attributeDict.setBelongAttribute(INVOLVE_DEPT);
                attributeDicts.add(attributeDict);
            });
        }

        //保存更改订单扩展信息
        if(CollectionUtils.isNotEmpty(attributeDicts)){
            attributeDictService.saveBatch(attributeDicts);
        }

        this.updateById(changeOrder);
    }

    @Override
    public PageResult<EngineeringChangeOrder> queryPage(PageRequest<EngineeringChangeOrder> pageRequest) {
        final EngineeringChangeOrder param = pageRequest.getParam();
        final LambdaQueryWrapper<EngineeringChangeOrder> lambda = new QueryWrapper<EngineeringChangeOrder>().lambda();
        this.buildCondition(lambda, param);
        final IPage<EngineeringChangeOrder> page = this.page(new Page<>(pageRequest.getPageNo(), pageRequest.getPageSize()), lambda);
        if(page!=null&&CollectionUtils.isNotEmpty(page.getRecords())){
            List<String> businessKeys = page.getRecords().stream().map(c->c.getChangeOrderId()).collect(Collectors.toList());
            Map<String, BpmProcessInstanceStatus> processMap = null;
            //获取业务流程状态
            ResultBody<List<BpmProcessInstanceStatus>> resultBody = camundaApi.queryProcessInstanceStatus(businessKeys);
            if (resultBody != null && CollectionUtils.isNotEmpty(resultBody.getData())) {
                processMap = resultBody.getData().stream().collect(Collectors.toMap(bp->bp.getBusinessKey(), bp->bp, (bp1, bp2) -> bp1));
            }

            Map<Object, Object> deptMap = redisService.hmget(RedisKey.DEPT_GROUP_TYPE);
            Map<Object, Object> userMap = redisService.hmget(RedisKey.USER_GROUP_TYPE);
            for (EngineeringChangeOrder changeOrder : page.getRecords()) {
                if(deptMap!=null){
                    if(StringUtils.isNotBlank(changeOrder.getApplyDept())){
                        changeOrder.setApplyDeptName(deptMap.get(changeOrder.getApplyDept())==null?"":deptMap.get(changeOrder.getApplyDept()).toString());
                    }
                }
                if(userMap!=null){
                    if(StringUtils.isNotEmpty(changeOrder.getApplyUser())){
                        changeOrder.setApplyUserName(userMap.get(changeOrder.getApplyUser())==null?"":userMap.get(changeOrder.getApplyUser()).toString());
                    }
                }
                if(processMap!=null && processMap.get(changeOrder.getChangeOrderId())!=null){
                    BpmProcessInstanceStatus process = processMap.get(changeOrder.getChangeOrderId());
                    changeOrder.setStatus(String.valueOf(process.getStatus()));
                    changeOrder.setProcessId(process.getProcessInstanceId());
                    changeOrder.setNodeName(process.getNodeName());
                    if (StringUtils.isNotBlank(process.getUserId())) {
                        if(process.getUserId().indexOf(CommonConstant.SpecialSign.COMMA.getName())!=-1){
                            String[] userIds= process.getUserId().split(CommonConstant.SpecialSign.COMMA.getName());
                            StringBuilder userName = new StringBuilder();
                            int size = userIds.length;
                            for (int i=0;i< size;i++) {
                                String name = userMap.get(userIds[i])==null?"":userMap.get(userIds[i]).toString();
                                if(i==size-1){
                                    userName.append(name);
                                }else{
                                    userName.append(name).append(CommonConstant.SpecialSign.COMMA.getName());
                                }
                            }
                            changeOrder.setApproveUserId(process.getUserId());
                            changeOrder.setApproveUserName(userName.toString());
                        }else{
                            changeOrder.setApproveUserId(process.getUserId());
                            changeOrder.setApproveUserName(userMap.get(process.getUserId())==null?"":userMap.get(process.getUserId()).toString());
                        }
                    }
                }
            }
        }

        PageResult<EngineeringChangeOrder> pr = new PageResult(page);
        return pr;
    }

    @Override
    public EngineeringChangeOrder getDetail(String changeOrderId) {
        EngineeringChangeOrder changeOrder = this.getById(changeOrderId);
        if(changeOrder!=null){
            ResultBody<List<FileBusiness>> resultBody = fileApi.getFileBusinessByIds(Arrays.asList(changeOrder.getChangeOrderId()));
            if(resultBody!=null&&CollectionUtils.isNotEmpty(resultBody.getData())){
                resultBody.getData().forEach(fb->{
                    if(CONTENT_FILE.equals(fb.getAttribute())){
                        changeOrder.setContentFiles(fb.getFileIds());
                    }else if(RESULT_FILE.equals(fb.getAttribute())){
                        changeOrder.setResultFiles(fb.getFileIds());
                    }
                });
            }

            Map<Object, Object> deptMap = redisService.hmget(RedisKey.DEPT_GROUP_TYPE);
            Map<Object, Object> userMap = redisService.hmget(RedisKey.USER_GROUP_TYPE);
            changeOrder.setApplyDeptName(deptMap.get(changeOrder.getApplyDept())==null?"":deptMap.get(changeOrder.getApplyDept()).toString());
            changeOrder.setApplyUserName(userMap.get(changeOrder.getApplyUser())==null?"":userMap.get(changeOrder.getApplyUser()).toString());

            List<BusinessAttributeDict> dicts = attributeDictService.queryByBusinessId(changeOrder.getChangeOrderId());
            if(CollectionUtils.isNotEmpty(dicts)){
                Map<String,List<BusinessAttributeDict>> dictMap = dicts.stream().collect(Collectors.groupingBy(BusinessAttributeDict::getBelongAttribute));
                dictMap.forEach((k,v)->{
                    if(INVOLVE_DEPT.equals(k)){
                        changeOrder.setInvolveDeptIds(v.stream().map(b->b.getDictCode()).collect(Collectors.toList()));
                    }else if(INVOLVE_FILE.equals(k)){
                        changeOrder.setInvolveFiles(v.stream().map(b->b.getDictCode()).collect(Collectors.toList()));
                    }
                });
            }

        }
        return changeOrder;
    }

    /**
     * 构造查询条件
     * @param lambda
     * @param param
     */
    private void buildCondition(LambdaQueryWrapper<EngineeringChangeOrder> lambda, EngineeringChangeOrder param){
        if(null == param) return;
        if(!org.springframework.util.StringUtils.isEmpty(param.getChangeOrderId())){
            lambda.eq(EngineeringChangeOrder::getChangeOrderId, param.getChangeOrderId());
        }
        if(!org.springframework.util.StringUtils.isEmpty(param.getItemName())){
            lambda.eq(EngineeringChangeOrder::getItemName, param.getItemName());
        }
        if(!org.springframework.util.StringUtils.isEmpty(param.getChangeCode())){
            lambda.eq(EngineeringChangeOrder::getChangeCode, param.getChangeCode());
        }
        if(!org.springframework.util.StringUtils.isEmpty(param.getApplyDept())){
            lambda.eq(EngineeringChangeOrder::getApplyDept, param.getApplyDept());
        }
        if(!org.springframework.util.StringUtils.isEmpty(param.getApplyUser())){
            lambda.eq(EngineeringChangeOrder::getApplyUser, param.getApplyUser());
        }
        if(!org.springframework.util.StringUtils.isEmpty(param.getSupplier())){
            lambda.eq(EngineeringChangeOrder::getSupplier, param.getSupplier());
        }
        if(!org.springframework.util.StringUtils.isEmpty(param.getClientAffirm())){
            lambda.eq(EngineeringChangeOrder::getClientAffirm, param.getClientAffirm());
        }
        if(!org.springframework.util.StringUtils.isEmpty(param.getChangeContent())){
            lambda.eq(EngineeringChangeOrder::getChangeContent, param.getChangeContent());
        }
        if(!org.springframework.util.StringUtils.isEmpty(param.getChangeResult())){
            lambda.eq(EngineeringChangeOrder::getChangeResult, param.getChangeResult());
        }
        if(!org.springframework.util.StringUtils.isEmpty(param.getChangeConclusion())){
            lambda.eq(EngineeringChangeOrder::getChangeConclusion, param.getChangeConclusion());
        }
        lambda.orderBy(true,false, EngineeringChangeOrder::getChangeOrderId);
    }
}
